Skip to content

feat(api): derive reference title and slug from summary#18322

Merged
betegon merged 6 commits into
masterfrom
api/operation-id-summary-title
Jun 10, 2026
Merged

feat(api): derive reference title and slug from summary#18322
betegon merged 6 commits into
masterfrom
api/operation-id-summary-title

Conversation

@betegon

@betegon betegon commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

Part of using OpenAPI operationId as a proper machine identifier (token) instead of a human sentence. Today the API reference renders the operationId as the page title and builds the URL slug from it (slugify(operationId)), so the misuse is load-bearing for our SEO'd doc URLs.

This makes the reference prefer the human-readable summary for both the title and the slug, falling back to operationId. It's a no-op today (no operations define summary yet → falls back to operationId, current behavior). Once the backend sets summary = the original sentence and operationId = a camelCase token, titles and slugs stay byte-identical while the operationId becomes a clean token.

Deprecation is encoded as a (DEPRECATED) prefix in the operationId; the strip/detect logic now runs on whichever source wins (summary || operationId), so deprecated endpoints keep their exact slug and title too.

Changes

  • resolveOpenAPI.ts: title (name) and slug derive from summary || operationId.
  • apiPage: don't render the summary <p> when it already equals the title.

Test plan

  • pnpm lint:ts clean for the changed files (pre-existing instrumentation*.ts SDK-version errors are unrelated).
  • No operation currently defines summary, so rendered titles and slugs are unchanged. Verified the slug stays identical once summary = the original sentence, since slugify runs on the same stripped string.

This is the SEO-foundation PR; the backend operationId→token + summary migration depends on it landing first.

The API reference uses the OpenAPI operationId as the page title and the URL
slug (slugify(operationId)). That blocks the backend from using operationId as
a proper machine token, because changing it would change every title and
(SEO-critical) URL.

Prefer the human-readable summary for the title and slug, falling back to
operationId. This is a no-op today (no operations define summary yet), and once
the backend sets summary = the original sentence, titles and slugs stay
byte-identical while operationId becomes a clean token. The deprecation prefix
is detected/stripped from whichever source wins, so deprecated endpoints keep
their exact slug too.
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
develop-docs Ready Ready Preview, Comment Jun 9, 2026 5:31pm
sentry-docs Ready Ready Preview, Comment Jun 9, 2026 5:31pm

Request Review

@sergical sergical left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Comment thread src/build/resolveOpenAPI.ts Outdated
Comment thread src/build/resolveOpenAPI.ts
Reading the (DEPRECATED) marker off the display title (summary || operationId)
would miss it once an op has a summary, since the marker sits on operationId.
Check both fields directly so deprecation detection is independent of which
string supplies the title.
Comment thread src/components/apiPage/index.tsx
name was stripped of the (DEPRECATED) prefix but summary was stored raw, so
the apiPage dedup (api.summary !== api.name) compared a stripped value to a
raw one — a prefixed summary would defeat the dedup and render the prefix in
the summary paragraph. Strip both consistently.
@betegon betegon merged commit 95b8fb7 into master Jun 10, 2026
23 checks passed
@betegon betegon deleted the api/operation-id-summary-title branch June 10, 2026 09:10
betegon added a commit to getsentry/sentry that referenced this pull request Jun 10, 2026
)

## Summary

OpenAPI `operationId` is meant to be a machine identifier, but Sentry
uses the human sentence (e.g. `Retrieve a Count of Replays for a Given
Issue or Transaction`). That sentence is what the generated
`@sentry/api` SDK turns into function names, and what the API reference
renders as the page title **and** URL slug.

This moves the sentence into `summary` (the human title) and sets
`operation_id` to a short camelCase token for the **replay** endpoints.
The SDK then gets clean names (`getOrganizationReplayCount`,
`listOrganizationReplays`, `getOrganizationReplay`, …), and — paired
with
[getsentry/sentry-docs#18322](getsentry/sentry-docs#18322),
which makes the reference derive its title/slug from `summary` — the
docs title and SEO-critical URLs stay **byte-identical**.

This is the **pilot area** of a broader operationId→token migration
(batched per CODEOWNERS area). A couple of replay GETs that were
mislabeled `list` are corrected here too (e.g. the replay *count* is a
`get`, not a `list`).

## Changes
- 10 replay endpoint files: `operation_id` → camelCase token, `summary`
= the original sentence.

## Test plan
- `make build-api-docs` (drf-spectacular) regenerates and passes
`--validate --fail-on-warn`; the regenerated spec shows the replay
operations with token operationIds, the sentence preserved as `summary`,
and `description` intact.
- prek (ruff/flake8/mypy + the `@extend_schema` response-type check)
passes on all changed files.

Depends on getsentry/sentry-docs#18322 landing first so docs
titles/slugs are unaffected.
pull Bot pushed a commit to pgoslatara/sentry that referenced this pull request Jun 10, 2026
…etsentry#117297)

## Summary

Second area of the operationId→token migration. OpenAPI `operationId` is
meant to be a machine identifier, but Sentry uses the human sentence —
which the generated `@sentry/api` SDK turns into function names and the
API reference renders as the page title + URL slug.

This moves the sentence into `summary` and sets `operation_id` to a
short camelCase REST token for the **dashboard** endpoints. The SDK gets
clean names; paired with the merged docs change (title/slug derive from
`summary`), the docs titles and SEO URLs stay byte-identical.

5 operations, 2 files, all textbook CRUD (no exceptions):
`listOrganizationDashboards` · `createOrganizationDashboard` ·
`getOrganizationDashboard` · `updateOrganizationDashboard` ·
`deleteOrganizationDashboard`

## Test plan
- `make build-api-docs` regenerates the spec and passes `--validate
--fail-on-warn`; dashboard ops show token operationIds with the sentence
preserved as `summary`.
- prek green (ruff/flake8/mypy + the `@extend_schema` response-type
check).

## Related (operationId→token migration)
- Convention documented in `src/AGENTS.md`: getsentry#117285
- Replays pilot (first area): getsentry#117166
- Docs SEO foundation (title/slug from summary):
getsentry/sentry-docs#18322 (merged)
pull Bot pushed a commit to pgoslatara/sentry that referenced this pull request Jun 10, 2026
…tsentry#117302)

## Summary

Third area of the operationId→token migration. Move the human sentence
into `summary` and set `operation_id` to a short camelCase REST token,
so the generated `@sentry/api` SDK gets clean names while docs
titles/slugs stay byte-identical (derived from `summary`).

5 operations, 2 files. The path is `/discover/saved/`, so the pure
structural token drops the resource noun (`…DiscoverSaved`). Overridden
to the endpoint's own term — `DiscoverSavedQuery` (per
`DiscoverSavedQuerySerializer`) — for clarity:

- `listOrganizationDiscoverSavedQueries`
- `createOrganizationDiscoverSavedQuery`
- `getOrganizationDiscoverSavedQuery`
- `updateOrganizationDiscoverSavedQuery`
- `deleteOrganizationDiscoverSavedQuery`

## Test plan
- `make build-api-docs` regenerates the spec and passes `--validate
--fail-on-warn`; operations show token operationIds with the sentence
preserved as `summary`.
- prek green (ruff/flake8/mypy + the `@extend_schema` response-type
check).

## Related (operationId→token migration)
- Convention doc (`src/AGENTS.md`): getsentry#117285
- Replays pilot: getsentry#117166 · Dashboards: getsentry#117297
- Docs SEO foundation: getsentry/sentry-docs#18322 (merged)
amy-chen23 pushed a commit to getsentry/sentry that referenced this pull request Jun 10, 2026
)

## Summary

OpenAPI `operationId` is meant to be a machine identifier, but Sentry
uses the human sentence (e.g. `Retrieve a Count of Replays for a Given
Issue or Transaction`). That sentence is what the generated
`@sentry/api` SDK turns into function names, and what the API reference
renders as the page title **and** URL slug.

This moves the sentence into `summary` (the human title) and sets
`operation_id` to a short camelCase token for the **replay** endpoints.
The SDK then gets clean names (`getOrganizationReplayCount`,
`listOrganizationReplays`, `getOrganizationReplay`, …), and — paired
with
[getsentry/sentry-docs#18322](getsentry/sentry-docs#18322),
which makes the reference derive its title/slug from `summary` — the
docs title and SEO-critical URLs stay **byte-identical**.

This is the **pilot area** of a broader operationId→token migration
(batched per CODEOWNERS area). A couple of replay GETs that were
mislabeled `list` are corrected here too (e.g. the replay *count* is a
`get`, not a `list`).

## Changes
- 10 replay endpoint files: `operation_id` → camelCase token, `summary`
= the original sentence.

## Test plan
- `make build-api-docs` (drf-spectacular) regenerates and passes
`--validate --fail-on-warn`; the regenerated spec shows the replay
operations with token operationIds, the sentence preserved as `summary`,
and `description` intact.
- prek (ruff/flake8/mypy + the `@extend_schema` response-type check)
passes on all changed files.

Depends on getsentry/sentry-docs#18322 landing first so docs
titles/slugs are unaffected.
pull Bot pushed a commit to dolfly/sentry that referenced this pull request Jun 17, 2026
…etsentry#117337)

## Summary

operationId→token migration, **batch 1 of 3** (core + api endpoints,
**83 ops / 50 files**). Moves the human sentence into `summary` and sets
`operation_id` to a short camelCase REST token so the generated
`@sentry/api` SDK gets clean names; docs titles/slugs stay
byte-identical (derived from `summary`).

Most are straight CRUD (`getOrganization`, `listProjectKeys`,
`updateProject`, …). Verb-corrected and ad-hoc overrides where the path
couldn't express intent:
- non-CRUD verbs: `addProjectTeam`, `addOrganizationMember`,
`linkProjectRepository`, `registerProjectServiceHook`,
`provisionOrganizationScimV2User`/`Group`
- singleton GETs → `get`: `getOrganizationProfilingFlamegraph`,
`getOrganizationSessions`, `getOrganizationStatsSummary`,
`getProjectEventSourceMapDebug`
- consistency/clarity: symbol-source detail ops singular
(`delete`/`updateProjectSymbolSource`),
`listOrganizationTraceItemAttributes`, `listProjectDebugFiles`

## Test plan
- prek green (ruff/flake8/mypy + `@extend_schema` response-type check).
- CI `api docs test` regenerates + validates the spec
(`--fail-on-warn`); operations show token operationIds with the sentence
preserved as `summary`.

## Related (operationId→token migration)
- Convention: getsentry#117285 · Merged: replays getsentry#117166, dashboards getsentry#117297,
discover getsentry#117302
- Docs SEO foundation: getsentry/sentry-docs#18322 (merged)
- Batches 2 & 3 to follow (issues/integrations/releases/workflow_engine;
preprod/monitors/sentry_apps/notifications/seer/feedback)

⚠️ Merge note: the schema publish job has no concurrency guard — **don't
merge the 3 batches simultaneously** (caused a partial-release race last
time). Space them out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants